package hw_8_1.reflect_Demo3;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 要求给定一个任意类的Class对象，使用Map<String,Object>集合存储对象的数据，其中K为属性名，V为属性值。
 * 现要求使用反射机制将Map集合存储的对象的数据动态赋值给对象相应的属性上。
 */
public class Test {
    public static void main(String[] args) throws Exception {
        List<Map<String,Object>> dataMap = new ArrayList<>();
        /**
         * Map<K, V> map = Map.of(k1, v1, k2, v2, ..., kn, vn);
         * 其中，K表示键的类型，V表示值的类型，k1, k2, ..., kn表示键，v1, v2, ..., vn表示值。注意，键和值必须非空且不可重复。
         */
        Map<String,Object> map1 = Map.of("name","小王","age",25);
        Map<String,Object> map2 = Map.of("name","小张","age",18);
        dataMap.add(map1);
        dataMap.add(map2);
        List<Person> personList = fillProps(Person.class, dataMap);
        System.out.println(personList);
    }


    /**
     *1、<T>：<T> 是一个泛型参数，其目的是允许方法在调用时，传递任意类型的clazz参数。
     *2、List<T>：该方法的返回类型是一个泛型列表 List<T>，表示填充后的对象列表。
     * 通过泛型类型参数 T，可以确保返回的列表中的元素类型与传入的 clazz 参数相一致。
     */
    public static <T> List<T> fillProps(Class<T> clazz, List<Map<String,Object>> dataMap) throws Exception {
        List<T> resultList = new ArrayList<>();
        for (Map<String, Object> map : dataMap) {
            T obj = clazz.getDeclaredConstructor().newInstance();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                String propertyName = entry.getKey();
                Object propertyValue = entry.getValue();
                /**
                 * 利用反射，通过clazz.getDeclaredField(propertyName)获取目标类中对应属性名的Field对象，
                 * 然后设置属性的可访问性为true，最后使用field.set(obj, propertyValue)方法将属性值设置到对象obj中。
                 */
                Field field = clazz.getDeclaredField(propertyName);
                field.setAccessible(true);
                field.set(obj,propertyValue);
            }
            resultList.add(obj);
        }
        return resultList;
    }
}
